package logic

import (
	"errors"
	"context"
	"shortUrl/models"
	"shortUrl/pkg/shortcode"
	"shortUrl/services/mysql"
	"shortUrl/services/redis"
	"time"
)

type LoginUrler interface {
	CreateUrl(ctx context.Context, req models.CreateUrlRequset) (*models.UrlResponse, error)
	GetOriginalURL(ctx context.Context,c string) (string ,error)
	DelateUrl() error
}
type LoginUrl struct {
	ServerUrl       mysql.ServiceUrler
	ShortCode       shortcode.ShortCoder
	defaultDuration time.Duration
	RedisCache      redis.Cacher
	baseUrl 	string
}
func NewLoginUrl(serverUrl mysql.ServiceUrler,shortCode shortcode.ShortCoder,redisCache redis.Cacher,defaultDuration time.Duration,baseUrl string) *LoginUrl{
	return &LoginUrl{
		ServerUrl:       serverUrl,
		ShortCode:       shortCode,
		defaultDuration: defaultDuration,
		RedisCache:      redisCache,
		baseUrl: 	baseUrl,

	}
}
func (l *LoginUrl) CreateUrl(ctx context.Context, req models.CreateUrlRequset) (*models.UrlResponse, error) {
	var expiresAt time.Time
	var customCod string
	var isCustom bool

	if req.CustomCode != "" {
		customCod = req.CustomCode
		isCustom = true
		_, err := l.ServerUrl.FindShortUrl(ctx,customCod);
		if err == nil {
			return nil,errors.New("短链已存在")
		}
	} else {
		customCod = l.ShortCode.GeratorShortCode(6)
		intNum := 5
		for i:=0;i < intNum; i++{
			customCod = l.ShortCode.GeratorShortCode(6)
			_, err := l.ServerUrl.FindShortUrl(ctx,customCod);
			if err != nil{
				break
			}
			if i == intNum-1{
				return nil,errors.New("短链生成失败，请重试")
			}
		}
		isCustom = false
	}
	if req.Duration == nil {
		expiresAt = time.Now().Add(l.defaultDuration)
	} else {
		expiresAt = time.Now().Add(time.Hour * time.Duration(*req.Duration))
	}

	if err := l.ServerUrl.CreateShortUrl(ctx, &models.Urls{
		OriginalUrl: req.OriginalUrl,
		ShortCode:   customCod,
		ExpiresAt:   &expiresAt,
		IsCustom: isCustom,
	}); err != nil {
		return nil, err
	}

	if err := l.RedisCache.SetUrl(ctx, customCod, req.OriginalUrl, time.Until(expiresAt)); err != nil {
		return nil, err
	}
	return &models.UrlResponse{
		OriginalUrl: req.OriginalUrl,
		ShortCodeUrl:   l.baseUrl+"/"+customCod,
	}, nil
}

func (l *LoginUrl) GetOriginalURL(ctx context.Context,shortCode string ) (string,error){
	cacheUrl, err := l.RedisCache.GetUrl(ctx,shortCode)
	if err == nil{
		return cacheUrl,nil
	}
	res,err := l.ServerUrl.FindShortUrl(ctx,shortCode);
	if err != nil{
		return "",err
	}
	err = l.RedisCache.SetUrl(ctx,shortCode,res.OriginalUrl,time.Until(*res.ExpiresAt))
	if err != nil{
		return "", err
	}

	return res.OriginalUrl,nil

}

func (l *LoginUrl) DelateUrl() error {
	if err := l.ServerUrl.DelateUrl();err != nil{
		return err
	}
	return nil
}